summaryrefslogtreecommitdiffstats
path: root/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/file_sys/fssystem/fssystem_integrity_verification_storage.cpp')
-rw-r--r--src/core/file_sys/fssystem/fssystem_integrity_verification_storage.cpp91
1 files changed, 91 insertions, 0 deletions
diff --git a/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.cpp b/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.cpp
new file mode 100644
index 000000000..2f73abf86
--- /dev/null
+++ b/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.cpp
@@ -0,0 +1,91 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/alignment.h"
+#include "core/file_sys/fssystem/fssystem_integrity_verification_storage.h"
+
+namespace FileSys {
+
+constexpr inline u32 ILog2(u32 val) {
+ ASSERT(val > 0);
+ return static_cast<u32>((sizeof(u32) * 8) - 1 - std::countl_zero<u32>(val));
+}
+
+void IntegrityVerificationStorage::Initialize(VirtualFile hs, VirtualFile ds, s64 verif_block_size,
+ s64 upper_layer_verif_block_size, bool is_real_data) {
+ // Validate preconditions.
+ ASSERT(verif_block_size >= HashSize);
+
+ // Set storages.
+ m_hash_storage = hs;
+ m_data_storage = ds;
+
+ // Set verification block sizes.
+ m_verification_block_size = verif_block_size;
+ m_verification_block_order = ILog2(static_cast<u32>(verif_block_size));
+ ASSERT(m_verification_block_size == 1ll << m_verification_block_order);
+
+ // Set upper layer block sizes.
+ upper_layer_verif_block_size = std::max(upper_layer_verif_block_size, HashSize);
+ m_upper_layer_verification_block_size = upper_layer_verif_block_size;
+ m_upper_layer_verification_block_order = ILog2(static_cast<u32>(upper_layer_verif_block_size));
+ ASSERT(m_upper_layer_verification_block_size == 1ll << m_upper_layer_verification_block_order);
+
+ // Validate sizes.
+ {
+ s64 hash_size = m_hash_storage->GetSize();
+ s64 data_size = m_data_storage->GetSize();
+ ASSERT(((hash_size / HashSize) * m_verification_block_size) >= data_size);
+ }
+
+ // Set data.
+ m_is_real_data = is_real_data;
+}
+
+void IntegrityVerificationStorage::Finalize() {
+ m_hash_storage = VirtualFile();
+ m_data_storage = VirtualFile();
+}
+
+size_t IntegrityVerificationStorage::Read(u8* buffer, size_t size, size_t offset) const {
+ // Succeed if zero size.
+ if (size == 0) {
+ return size;
+ }
+
+ // Validate arguments.
+ ASSERT(buffer != nullptr);
+
+ // Validate the offset.
+ s64 data_size = m_data_storage->GetSize();
+ ASSERT(offset <= static_cast<size_t>(data_size));
+
+ // Validate the access range.
+ ASSERT(R_SUCCEEDED(IStorage::CheckAccessRange(
+ offset, size, Common::AlignUp(data_size, static_cast<size_t>(m_verification_block_size)))));
+
+ // Determine the read extents.
+ size_t read_size = size;
+ if (static_cast<s64>(offset + read_size) > data_size) {
+ // Determine the padding sizes.
+ s64 padding_offset = data_size - offset;
+ size_t padding_size = static_cast<size_t>(
+ m_verification_block_size - (padding_offset & (m_verification_block_size - 1)));
+ ASSERT(static_cast<s64>(padding_size) < m_verification_block_size);
+
+ // Clear the padding.
+ std::memset(static_cast<u8*>(buffer) + padding_offset, 0, padding_size);
+
+ // Set the new in-bounds size.
+ read_size = static_cast<size_t>(data_size - offset);
+ }
+
+ // Perform the read.
+ return m_data_storage->Read(buffer, read_size, offset);
+}
+
+size_t IntegrityVerificationStorage::GetSize() const {
+ return m_data_storage->GetSize();
+}
+
+} // namespace FileSys